package com.bestillet.kyllingogco;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.AsyncTask.Status;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

public class ShopActivity extends Activity {
	public static final String EXTRA_MESSAGE = "message";
    public static final String PROPERTY_REG_ID = "registration_id";

    private static final String PROPERTY_APP_VERSION = "appVersion";
    private static final String SENDER_ID = "397847020641";

	private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

    private GoogleCloudMessaging gcm;
    
    private String regid;
    
	private ArrayList<Shop> shops;

	private AlertDialog dialog;
	private ListView list;
	private Context context;
	
	private SharedPreferences preferences;
	private ShopApplication app;
	private LoadingDialog loading;
	private RegistrationTask rTask;
	private ShopTask sTask;
	private CardTask cTask;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.shops);
		
		context = this;
		
		preferences = getSharedPreferences("Kylling & Co", MODE_PRIVATE);
		app = (ShopApplication) getApplicationContext();
		app.setKundeId(150);
		
		list = (ListView) findViewById(android.R.id.list);
		list.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
				app.setShop(shops.get(position));
				app.clearCategories();
				Intent intent = new Intent(context, MainActivity.class);
				intent.putExtra("shop", shops.get(position));
				startActivity(intent);
			}
		});
		
		if (checkPlayServices()) {
            gcm = GoogleCloudMessaging.getInstance(this);
            regid = getRegistrationId(context);

            if (regid.isEmpty()) {
                registerInBackground();
            }
        } else {
            Log.i("Shop", "No valid Google Play Services APK found.");
        }
	}
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		
		if (sTask != null)
			if (sTask.getStatus() == Status.RUNNING)
				sTask.cancel(true);
		
		if (cTask != null)
			if (cTask.getStatus() == Status.RUNNING)
				cTask.cancel(true);
		
		if (rTask != null)
			if (rTask.getStatus() == Status.RUNNING)
				rTask.cancel(true);
	}
	
	@Override
	protected void onResume() {
		super.onResume();
	    checkPlayServices();

		loading = new LoadingDialog(this);
		loading.show();
		
		sTask = new ShopTask();
		sTask.execute();
		
		cTask = new CardTask();
		cTask.execute();
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		if (dialog != null)
			if (dialog.isShowing())
				dialog.dismiss();
	}
	
	private boolean checkPlayServices() {
	    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
	    if (resultCode != ConnectionResult.SUCCESS) {
	        if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
	            GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show();
	        } else {
	            Log.i("Shop", "This device is not supported.");
	        }
	        return false;
	    }
	    return true;
	}
	
	private String getRegistrationId(Context context) {
	    String registrationId = preferences.getString(PROPERTY_REG_ID, "");
	    if (registrationId.isEmpty()) {
	        Log.i("Shop", "Registration not found.");
	        return "";
	    }
	    
	    int registeredVersion = preferences.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
	    int currentVersion = getAppVersion(context);
	    if (registeredVersion != currentVersion) {
	        Log.i("Shop", "App version changed.");
	        return "";
	    }
	    return registrationId;
	}
	
	private static int getAppVersion(Context context) {
	    try {
	        PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
	        return packageInfo.versionCode;
	    } catch (NameNotFoundException e) {
	        throw new RuntimeException("Could not get package name: " + e);
	    }
	}
	
	private void registerInBackground() {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... params) {
                String msg = "";
                try {
                    if (gcm == null) {
                        gcm = GoogleCloudMessaging.getInstance(context);
                    }
                    regid = gcm.register(SENDER_ID);
                    msg = "Device registered, registration ID=" + regid;

                    sendRegistrationIdToBackend();
                    storeRegistrationId(context, regid);
                } catch (IOException ex) {
                    msg = "Error :" + ex.getMessage();
                    //TODO
                    // If there is an error, don't just keep trying to register.
                    // Require the user to click a button again, or perform
                    // exponential back-off.
                }
                return msg;
            }

            @Override
            protected void onPostExecute(String msg) {
                Log.d("Shop", msg);
            }
        }.execute(null, null, null);
    }
	
	private void sendRegistrationIdToBackend() {
		String phone = preferences.getString("phone", "");
		if (phone.length() > 0) {
			rTask = new RegistrationTask();
			rTask.execute();
		}
	}
	
	private void storeRegistrationId(Context context, String regId) {
	    int appVersion = getAppVersion(context);
	    Log.i("Shop", "Saving regId on app version " + appVersion);
	    SharedPreferences.Editor editor = preferences.edit();
	    editor.putString(PROPERTY_REG_ID, regId);
	    editor.putInt(PROPERTY_APP_VERSION, appVersion);
	    editor.commit();
	}
	
	private class RegistrationTask extends AsyncTask<Void, Void, Boolean> {
    	@Override
		protected Boolean doInBackground(Void... params) {
			try {
				String phone = preferences.getString("phone", "");
				int shopId = preferences.getInt("shopId", 150);
				InputStream in = Server.post(Server.REGISTER, Server.getAuthenticationNotification(regid, phone, shopId, app.getKundeId()));
				XmlPullParser parser = Server.toXmlParser(in);
				int idx = XmlParser.getNotificationId(parser);
				return (idx != -1);
			} catch (IOException e) {
    			Log.e("Shop", "IOException: " + e.getMessage());
    			return false;
    		} catch (XmlPullParserException e) {
    			Log.e("Shop", "XmlPullParserException: " + e.getMessage());
    			return false;
    		} catch (NullPointerException e) {
    			Log.e("Shop", "NullPointerException: " + e.getMessage());
    			return false;
    		} catch (IllegalArgumentException e) {
    			Log.e("Shop", "IllegalArgumentException: " + e.getMessage());
    			return false;
    		}
    	}
    
	    @Override
	    protected void onPostExecute(Boolean success) {
	    	if (!success) {
	    		Editor editor = preferences.edit();
				editor.remove(PROPERTY_REG_ID);
				editor.commit();
	    	}
	    	loading.dismiss();
	    }
	}
	
	private class ShopTask extends AsyncTask<Void, Void, Boolean> {
    	@Override
		protected Boolean doInBackground(Void... params) {
    		try {
    			InputStream in = Server.post(Server.SHOPS, Server.getAuthenticationShop(context));
    			XmlPullParser parser = Server.toXmlParser(in);
    			shops = XmlParser.getShops(parser);
    			in.close();
    		} catch (IOException e) {
    			Log.e("Shop", "IOException: " + e.getMessage());
    			return false;
    		} catch (XmlPullParserException e) {
    			Log.e("Shop", "XmlPullParserException: " + e.getMessage());
    			return false;
    		} catch (NullPointerException e) {
    			Log.e("Shop", "NullPointerException: " + e.getMessage());
    			return false;
    		} catch (IllegalArgumentException e) {
    			Log.e("Shop", "IllegalArgumentException: " + e.getMessage());
    			return false;
    		}
    		return true;
    	}
    
	    @Override
	    protected void onPostExecute(Boolean success) {
	    	if (success) {
	    		app.clearShops();
	    		app.addShops(shops);
	    		
				ShopArrayAdapter adapter = new ShopArrayAdapter(context, shops);
				list.setAdapter(adapter);
				
				if (app.getShops().size() > 0) {
					// Check if this version is up to date
    				try {
    					Shop shop = app.getShops().get(0);
    					PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0);
    	    			if (info.versionCode < shop.getVersion()) {
    	    				AlertDialog.Builder builder = new AlertDialog.Builder(context);
    	    	    		builder.setMessage(R.string.dialog_version_message)
    	    	    		       .setTitle(R.string.dialog_version_title)
    	    	    		       .setCancelable(false)
    	    	    		       .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
    	    							@Override
    	    							public void onClick(DialogInterface dialog, int which) {
    	    								try {
    	    									startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName())));
    	    								} catch (ActivityNotFoundException  e) {
    	    									startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName())));
    	    								}
    	    							}
    	    						});
    	    	    		dialog = builder.create();
    	    	    		dialog.show();
    	    			} else {
    	    				String n = preferences.getString("name", "");
    	    				String p = preferences.getString("phone", "");
    	    				String e = preferences.getString("email", "");
    	    				
    	    				if (n.length() <= 0 || p.length() <= 0 || e.length() <= 0) {
    	    					Intent customer = new Intent(context, CustomerActivity.class);
    	    					startActivity(customer);
    	    				}
    	    			}
    				} catch (NameNotFoundException e) { }
				} else {
					AlertDialog.Builder builder = new AlertDialog.Builder(context);
		    		builder.setMessage(R.string.error_no_shops)
		    		       .setTitle(R.string.error)
		    		       .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog, int which) { }
							});
		    		AlertDialog dialog = builder.create();
		    		dialog.show();
				}
	    	} else {
	    		AlertDialog.Builder builder = new AlertDialog.Builder(context);
	    		builder.setMessage(R.string.error_shops)
	    		       .setTitle(R.string.error)
	    		       .setPositiveButton(R.string.yes, new OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog, int which) {
								sTask = new ShopTask();
								sTask.execute();
								loading.show();
							}
						})
						.setNegativeButton(R.string.no, new OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog, int which) {
								finish();
							}
						});
	    		AlertDialog dialog = builder.create();
	    		dialog.show();
	    	}
	    	loading.dismiss();
	    }
	}
	
	private class CardTask extends AsyncTask<Void, Void, Boolean> {
		private ArrayList<Card> cards;
		
    	@Override
		protected Boolean doInBackground(Void... params) {
    		try {
    			InputStream in = Server.post(Server.CARD, Server.getAuthenticationCard(context));
    			XmlPullParser parser = Server.toXmlParser(in);
    			cards = XmlParser.getCards(parser);
    			in.close();
    		} catch (IOException e) {
    			Log.e("Shop", "IOException: " + e.getMessage());
    			return false;
    		} catch (XmlPullParserException e) {
    			Log.e("Shop", "XmlPullParserException: " + e.getMessage());
    			return false;
    		} catch (NullPointerException e) {
    			Log.e("Shop", "NullPointerException: " + e.getMessage());
    			return false;
    		} catch (IllegalArgumentException e) {
    			Log.e("Shop", "IllegalArgumentException: " + e.getMessage());
    			return false;
    		}
    		return true;
    	}
    
	    @Override
	    protected void onPostExecute(Boolean success) {
	    	if (success) {
				app.clearCards();
				app.addCards(cards);
	    	}
			loading.dismiss();
	    }
	}
}